﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Snowdreamist.Threading;

namespace SNSpirit.Domain
{
    public delegate void LoadAction<T>(T obj);

    public class LazyDomainEntity : StatusDomainEntity
    {
        public LazyDomainEntity(LoadAction<LazyDomainEntity> action, bool isAllowMultiLoad = false)
        {
            if (action == null)
                throw new ArgumentNullException("action");
            this._loadAction = action;
            this._isAllowMultipleLoadAction = isAllowMultiLoad;
        }

        /// <summary>
        /// IsLoaded
        /// </summary>
        public bool IsLoaded { get; private set; }

        /// <summary>
        /// Load this entity
        /// </summary>
        public virtual void Load()
        {
            if (!this._isAllowMultipleLoadAction || (this._isAllowMultipleLoadAction && !this.IsLoaded))
            {
                if (Monitor.TryEnter(this._loadLock))
                {
                    // enter
                    try
                    {
                        this.EnterBusy();
                        // load
                        this.IsLoaded = true;
                        this.OnLoaded();
                    }
                    catch (Exception error)
                    {
                        this.OnErrorOccurred(error, "Load");
                    }
                    finally
                    {
                        this.ExitBusy();
                        Monitor.Exit(this._loadLock);
                    }
                }
            }
        }

        /// <summary>
        /// Load this entity asynchronously
        /// </summary>
        public virtual void LoadAsync()
        {
            BackgroundJob.Run(new Action(this.Load), "DomainLazyEntity.Load");
        }

        protected void OnLoaded()
        {
            if (this.Loaded != null)
                this.Loaded(this, new EventArgs());
        }

        public event EventHandler Loaded;

        #region private

        private readonly object _loadLock = new object();

        private LoadAction<LazyDomainEntity> _loadAction;

        private bool _isAllowMultipleLoadAction;

        #endregion private
    }
}